package com.onpositive.mediawiki.propertyparser;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;

import storage.v1.DefaultParserProvider;
import storage.v1.ParserV2;
import storage.v1.ValuesExtractorV1;

import com.onpositive.data.units.DateWithAccuracy;
import com.onpositive.semantic.model.api.meta.IMeta;
import com.onpositive.semantic.model.api.property.IPropertyProvider;
import com.onpositive.units.AbstractPreprocessor;
import com.onpositive.units.AbstractValueParser;
import com.onpositive.units.ParsedDate;
import com.onpositive.units.ParsedValue;

public class DateParser extends RangeParser<ParsedDate> {
	
	private static final String META_KEY_ERA_SET_DIRECTLY = "era-set-directly";
	private static final String META_KEY_LONELY_BOUND = "lonely-bound";
	private static final String PIECE_MARK_DEFAULT = "def";
	private static final String PIECE_MARK_INTEGER = "integer";
	private static final String PIECE_MARK_MONTH_LONG = "month-long";
	private static final String PIECE_MARK_MONTH_SHORT = "month-short";
	private static final String PIECE_MARK_ERA_DESIGNATOR = "era-designator";

	private static HashSet<String> eraDesignators = new HashSet<String>( Arrays.asList( new String[]{"ad","bc"}));
	
	private static HashSet<String> monthsLong = new HashSet<String>( Arrays.asList( new String[]{
			"january"  , "february", "march"   , "april"    ,
			"may"	   , "june"	   , "july"	   , "august"   ,
			"september", "october" , "november", "december" } ) ) ;
	
	private static HashSet<String> monthsShort = new HashSet<String>( Arrays.asList( new String[]{
			"jan", "feb", "mar", "apr",
			"may", "jun", "jul", "aug",
			"sep", "oct", "nov", "dec"  } ) ) ;
	
	private static String[] seasons = {"winter","spring","summer","autumn"} ;
	
	public DateParser(){
		super( ParsedDate.class, ParsedDate.ID ) ;
	}

	@Override
	protected String preprocess(String s, IMeta meta,	IPropertyProvider propertyProvider, Map<String, Object> metaInfo)
	{
		String str = super.preprocess(s, meta, propertyProvider, metaInfo) ;
		if(str == null)
			str = s ;

		String value = ParserV2.killNoBreakSpace( str ) ;
		value = killParasiteWords2( value ) ;		
		value = value.replaceAll(",+", ",") ;
		value = value.replaceAll("\\s+", " ") ;
		value = value.replaceAll("(\\d)(A.D.)", "$1AD") ;
		value = value.replaceAll("(\\d)(B.C.)", "$1BC") ;
		value = value.replaceAll("(\\d)( )(A.D.)( |\\z)", "$1$2AD$4") ;
		value = value.replaceAll("(\\d)( )(B.C.)( |\\z)", "$1$2BC$4") ;
		
//we do not replace spaces and underlines here because of range delimiters
//		value = value.replace(" ",",");
//		value = value.replace("_",",");
		
		return value ;
	}
	
	@Override
	protected ArrayList<Block<ParsedDate>> parseNonRangeValues(
			String _str,
			int startIndex,
			int endIndex,
			int delimeterEnd,
			IMeta meta,
			IPropertyProvider propertyProvider,
			Map<String, Object> metaInfo,
			String comment )
		{
		if( startIndex == _str.length() )
			return null ;
		
		ArrayList<Block<ParsedDate>> result = new ArrayList<Block<ParsedDate>>() ;
		
		String str = _str.toLowerCase() ;
		//str = str.replace(" ",",");
		//str = str.replace("_",",");
		//str = str.replace(".",",");
		str = str.replaceAll("[^\\da-zA-Z\\(\\)]",",");
		
		ArrayList<Integer> barriers = markBarriers(startIndex, endIndex, str);
		ArrayList<String> pieces = cutToPieces( str, barriers ) ;
		ArrayList<String> piecesMarks = markPieces( pieces ) ;
		
		extractBlocks(_str, comment, result, barriers, pieces, piecesMarks);
		
		if( delimeterEnd < _str.length() ){
			int ind0 = str.charAt(delimeterEnd) == ',' ? delimeterEnd+1 : delimeterEnd ;
			int ind1 = ind0-1 ;
			
			for( int i = 0 ; i < 3 ; i++ ){
				ind1 = str.indexOf(',',ind1+1) ;
				if( ind1 < 0 ){
					ind1 = str.length() ;
					break ;
				}
			}
			
			ArrayList<Block<ParsedDate>> appendixList = new ArrayList<Block<ParsedDate>>() ;
			ArrayList<Integer> appendixBarriers = markBarriers( ind0, ind1, str);
			ArrayList<String> appendixPieces = cutToPieces( str, appendixBarriers ) ;
			ArrayList<String> appendixPiecesMarks = markPieces( appendixPieces ) ;
			
			extractBlocks(_str, comment, appendixList, appendixBarriers, appendixPieces, appendixPiecesMarks );
			
			mergeAppendix( _str, result , appendixList, comment ) ;
		}
		
		return result.size() != 0 ? result : null ;
	}

	private void mergeAppendix(
			String str,
			ArrayList<Block<ParsedDate>> result,
			ArrayList<Block<ParsedDate>> appendixList,
			String comment )
	{
		if( appendixList.isEmpty() ){
			if( !result.isEmpty() ){
				Block<ParsedDate> blk = result.get( result.size()-1 );
				blk.putMetaInfo( META_KEY_LONELY_BOUND, "lower" ) ;
			}
			return ;
		}
		if( result.isEmpty() ){
			Block<ParsedDate> blk = appendixList.get(0);
			blk.putMetaInfo( META_KEY_LONELY_BOUND, "upper" ) ;
			result.add( blk) ;
			return ;
		}
		
		Block<ParsedDate> upperBlock = appendixList.iterator().next();		
		Block<ParsedDate> lowerBlock = result.get(result.size()-1);
		
		DateWithAccuracy upperDate = (DateWithAccuracy) upperBlock.getVal().value() ;
		DateWithAccuracy lowerDate = (DateWithAccuracy) lowerBlock.getVal().value() ;
		
		if( upperDate.getAccuracy() == DateWithAccuracy.ACCURACY_YEAR ){
			int uYear = upperDate.getCalendar().get( GregorianCalendar.YEAR ) ;
			int lYear = lowerDate.getCalendar().get( GregorianCalendar.YEAR ) ;
			
			if( uYear < lYear ){
				int l = (""+uYear).length();
				if( l == 2 || l == 1 ){
					int ord = 1 ;
					for(int i = 0 ; i < l ; i++)
						ord *= 10 ;
					
					int yearTmp = ( lYear / ord ) * ord ;
					uYear += yearTmp ;										
				}
				else
					return ;
				
				upperDate.getCalendar().set( GregorianCalendar.YEAR, uYear ) ;
			}			
		}
		
		ParsedDate rangeDate = new ParsedDate(lowerDate, upperDate, comment) ;
		Block<ParsedDate> rangeBlock = new Block<ParsedDate>( str, lowerBlock.getStart(), upperBlock.getEnd(), rangeDate ) ;
		result.set( result.size()-1, rangeBlock ) ;		
	}

	private void extractBlocks(String _str, String comment,
			ArrayList<Block<ParsedDate>> result, ArrayList<Integer> barriers,
			ArrayList<String> pieces, ArrayList<String> piecesMarks) {
		int size = pieces.size() ;
		
		for( int i = 0 ; i < size ; i++ ){
			
			Block<ParsedDate> blk0 = null ;
			int increment = 0 ;
			String era = null ;
			String mark0 = piecesMarks.get(i) ;
			if( mark0.equals(PIECE_MARK_MONTH_LONG) || mark0.equals(PIECE_MARK_MONTH_SHORT) ){
				//MMMM,dd,yyyy & MMMM,yyyy
				if( i == size-1 )
					continue ;
				
				String mark1 = piecesMarks.get(i+1) ;
				if( !mark1.equals(PIECE_MARK_INTEGER) )
					continue ;
				
				String mark2 = ( i != size-2 ) ? piecesMarks.get(i+2) : null ;
				
				if( i != size-2 && mark2.equals(PIECE_MARK_INTEGER) ){
					//MMMM,dd,yyyy
					
					increment = 2 ;
					if( i < size-3 ){
						String mark3 = piecesMarks.get(i+3) ;
						if( mark3.equals(PIECE_MARK_ERA_DESIGNATOR) ){
							era = pieces.get(i+3) ;
							increment = 3 ;
						}
					}
					String datePattern = "MMMM,dd,yyyy" ;
					blk0 = produceDate3( _str, i , 3 , era, datePattern, pieces , barriers, comment ) ;					
				}
				Block<ParsedDate> blk1 = null ;
				{
					//MMMM,yyyy
					era = null ;
					if( i < size-2 ){
						String mark3 = piecesMarks.get(i+2) ;
						if( mark3.equals(PIECE_MARK_ERA_DESIGNATOR) ){
							era = pieces.get(i+2) ;
							increment = Math.max(increment, 2) ;
						}
					}
					String datePattern = "MMMM,yyyy" ;
					blk1 = produceDate3( _str, i , 2 , era, datePattern, pieces , barriers, comment ) ;
				}
				
				if( blk0 == null ){
					blk0 = blk1 ;
					increment = 1 ;
				}
				else if( blk1 != null )
					blk0.putMetaInfo("alt", blk1) ;					
			}
			else if( mark0.equals(PIECE_MARK_INTEGER) ){
				//dd,MMMM,yyyy & dd,MM,yyyy & yyyy,MMMM & yyyy,MM & yyyy				
				
				era = null ;
				if( i < size-1 ){
					String mark3 = piecesMarks.get(i+1) ;
					if( mark3.equals(PIECE_MARK_ERA_DESIGNATOR) ){
						era = pieces.get(i+1) ;
						increment = Math.max(increment, 1) ;
					}
				}
				
				Block<ParsedDate> yearBlock = produceDate3( _str, i , 1 ,era, "yyyy", pieces , barriers, comment ) ;
				if(era != null){
					result.add(yearBlock) ;
					return ;
				}
				
				
				if( i == size-1 ){
					// yyyy, possibly
					blk0 = yearBlock ;
				}
				else{
					String mark1 = piecesMarks.get(i+1) ;
					if( mark1.equals(PIECE_MARK_MONTH_LONG) || mark1.equals(PIECE_MARK_MONTH_SHORT) ){
						//dd,MMMM,yyyy & yyyy,MMMM
						
						String mark2 = ( i != size-2 ) ? piecesMarks.get(i+2) : null ;
						
						if( i != size-2 && mark2.equals(PIECE_MARK_INTEGER) ){
							//dd,MMMM,yyyy
							era = null ;
							increment = 2 ;
							if( i < size-3 ){
								String mark3 = piecesMarks.get(i+3) ;
								if( mark3.equals(PIECE_MARK_ERA_DESIGNATOR) ){
									era = pieces.get(i+3) ;
									increment = Math.max(increment, 3) ;
								}
							}
							String datePattern = "dd,MMMM,yyyy" ;
							blk0 = produceDate3( _str, i , 3 , era, datePattern, pieces , barriers, comment ) ;							
						}
						Block<ParsedDate> blk1 = null ;
						{
							//yyyy,MMMM
							era = null ;
							if( i < size-2 ){
								String mark3 = piecesMarks.get(i+2) ;
								if( mark3.equals(PIECE_MARK_ERA_DESIGNATOR) ){
									era = pieces.get(i+2) ;
									increment = Math.max(increment, 2) ;
								}
							}
							String datePattern = "yyyy,MMMM" ;
							blk1 = produceDate3( _str, i , 2 , era, datePattern, pieces , barriers, comment ) ;
						}
						if( blk0 == null ){
							blk0 = blk1 ;
							increment = 1 ;
						}
						else if( blk1 != null )
							blk0.putMetaInfo("alt", blk1) ;					
					}
				}
				if( blk0 == null ){
					blk0 = yearBlock ;
					increment = 0 ;
				}				
			}			
			
			if( blk0 != null )
				result.add(blk0) ;
			
			i += increment ;
		}
	}

	
	private static byte[] accuracies = new byte[]{
		-1 ,
		DateWithAccuracy.ACCURACY_YEAR,
		DateWithAccuracy.ACCURACY_MONTH,
		DateWithAccuracy.ACCURACY_DAY } ;
	
	private Block<ParsedDate> produceDate3(
			String inputString,
			int start,
			int count,
			String era ,
			String datePattern,
			ArrayList<String> pieces,
			ArrayList<Integer> barriers,
			String comment )
	{
		StringBuilder bld = new StringBuilder() ;
		for( int i = 0 ; i < count ; i++ ){
			bld.append(pieces.get(start+i)) ;
			bld.append(",") ;
		}
		String str = bld.substring( 0, bld.length()-1 ) ;
		ParsedDate pd = null ;
		byte accuracy = accuracies[count] ;
		boolean eraSetDirectly = false ;
		try{
			DateFormat dateInstance = new SimpleDateFormat( datePattern, Locale.US );
			Date parse = dateInstance.parse( str );
			pd = new ParsedDate(parse, accuracy , getDefaultComment(comment) );
			if( era != null && ( era.equals("ad") || era.equals("bc") ) )
			{
				int eraValue = era.equals("ad") ? GregorianCalendar.AD : GregorianCalendar.BC ;
				((DateWithAccuracy)pd.getUpperBound()).getCalendar().set( GregorianCalendar.ERA, eraValue) ;
				eraSetDirectly = true ;
			}
		} catch (ParseException e) {
		}
		if( pd == null )
			return null ;
		
		int blockStart = barriers.get( 2*start ) ;
		int blockEnd   = barriers.get( 2*(start+count-1)+1 ) ;
		
		Block<ParsedDate> blk = new Block<ParsedDate>( inputString, blockStart, blockEnd, pd ) ;
		if(eraSetDirectly)
			blk.putMetaInfo(META_KEY_ERA_SET_DIRECTLY, era ) ;
		
		return blk;
	}

	
	private static ArrayList<String> markPieces(ArrayList<String> pieces)
	{
		ArrayList<String> result = new ArrayList<String>() ;
		for( String piece : pieces ){
			
			if( piece.length() == 0 ){
				result.add( PIECE_MARK_DEFAULT ) ;
				continue ;
			}
			
			if( monthsLong.contains(piece) ){
				result.add(PIECE_MARK_MONTH_LONG) ;
				continue ;
			}
			if( monthsShort.contains(piece) ){
				result.add(PIECE_MARK_MONTH_SHORT) ;
				continue ;
			}
			if( eraDesignators.contains(piece) ){
				result.add(PIECE_MARK_ERA_DESIGNATOR) ;
				continue ;
			}	
			
			int length = piece.length();
			boolean isDigit = true ;
			for( int i = 0 ; i < length ; i++ ){
				boolean charIsDigit = Character.isDigit( piece.charAt(i) ) ;
				if( charIsDigit )
					continue ;
				
				isDigit = false;
				break ;
			}
			if( isDigit ){
				result.add( PIECE_MARK_INTEGER ) ;
				continue ;
			}
			
			result.add( PIECE_MARK_DEFAULT ) ;			
		}		
		
		return result ;
	}

	private static ArrayList<String> cutToPieces(String str, ArrayList<Integer> barriers) {

		ArrayList<String> result = new ArrayList<String>() ;
		for( int i = 0 ; i < barriers.size() ; i +=2 )
		{
			Integer start = barriers.get(i);
			Integer end = barriers.get(i+1);
			String piece = str.substring( start, end ).trim();
			result.add( piece ) ;
		}		
		return result ;
	}

	private static ArrayList<Integer> markBarriers(int startIndex, int endIndex, String str)
	{
		try{
			if( startIndex == endIndex )
				return new ArrayList<Integer>( Arrays.asList( new Integer[]{ startIndex, endIndex} ) ) ;
	
			ArrayList<Integer> barriers = new ArrayList<Integer>() ;
			int prev = str.charAt(startIndex) ==',' ? startIndex+1 : startIndex ;
			barriers.add(prev) ;
			int lastIndex = Math.max(prev, str.charAt(endIndex-1) == ',' ? endIndex-1 : endIndex );
			for( int i = str.indexOf(",", prev) ; i >= 0 && i < lastIndex ; i = str.indexOf(",", prev) )
			{
				for( int j = prev ; j < i-1 ; j++ )
				{
					char currChar = str.charAt( j ) ;
					char nextChar = str.charAt(j+1) ;
					
					if( ( Character.isDigit(currChar) && Character.isLetter(nextChar) ) || 
						( Character.isDigit(nextChar) && Character.isLetter(currChar) )    )
					{
						barriers.add(j+1) ;
						barriers.add(j+1) ;
					}				
				}
				barriers.add(i) ;			
				prev = i+1 ;	
				barriers.add( prev ) ;
			}
			barriers.add(lastIndex) ;
			
			return barriers ;
		
		}catch (StringIndexOutOfBoundsException e) {
			e.printStackTrace();
			return new ArrayList<Integer>( Arrays.asList( new Integer[]{ endIndex, endIndex }) );
		}
	}	

	public ParsedValue parse0(String s, IMeta meta, IPropertyProvider propertyProvider,Map<String,Object> metaInfo, String comment) {
		
		String value = ParserV2.killWikiRefsLeaveCaptions(s) ;
		value = ParserV2.killNoBreakSpace( value ) ;
		value = killParasiteWords( value ) ;
		value = value.toLowerCase() ;			
		value = value.replace(".",",");
		value = value.replace(" ",",");
		value = value.replaceAll(",+", ",") ;	
		
		ParsedDate result = produceDate( value, comment,true );
		if( result != null )
			return result ;
		
		String[] strArr = value.split(",") ;
		int l = strArr.length ;
		
		StringBuilder bld = new StringBuilder() ;
		for( int k = 2; k >= 0 ; k-- )
		{
			for( int i = 0 ; i < l-k ; i++ )
			{
				bld.delete(0, bld.length()) ;
				for( int j = 0 ; j < k+1 ; j++ )
				{
					bld.append( strArr[i+j]) ;
					bld.append(",") ;
				}
				value = bld.substring(0,bld.length()-1) ;
				result = produceDate(value,comment,true) ;
				if( result != null )
					return result ;
			}
		}
		return DefaultParserProvider.getDefaultValueParser().parse( s, meta, propertyProvider, metaInfo, comment ) ;
	}

	public ParsedDate produceDate(String value, String comment, boolean useExtendedMethod ) {
		try {
			DateFormat dateInstance = new SimpleDateFormat("dd,MM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("dd,MMMM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMM,dd,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMM,yyyy", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("yyyy,MMMM", Locale.US );
			Date parse = dateInstance.parse(value);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		String value0 = value.replace(",", "") ;
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("ddMMMMyyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_DAY, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("MMMMyyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_MONTH, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}		
		
		if( !useExtendedMethod )
			return null ;
		
		try{
			DateFormat dateInstance = new SimpleDateFormat("yyyy", Locale.US );
			Date parse = dateInstance.parse(value0);
			return new ParsedDate(parse, DateWithAccuracy.ACCURACY_YEAR, getDefaultComment(comment) );
		} catch (ParseException e) {
			//e.printStackTrace() ;		
		}
		return null ;
	}
	
	private static String killParasiteWords(String value) {
		
		String result = value ;

		result = result.replaceAll(" of ", " ") ;
		result = result.replaceAll(" on ", " ") ;		
		result = result.replaceAll("\\Aof\\s*", "") ;		
		result = result.replaceAll("\\Aon\\s*", "") ;
		result = result.replaceAll("(\\d)(th)", "$1") ;
		result = result.replaceAll("(\\d)(st)", "$1") ;
		result = result.replaceAll("\\A\\s*", "\\A") ;
		result = result.replaceAll("\\s*\\z", "\\z") ;

		return result ;
	}


	private static String killParasiteWords2(String value) {
		
		String result = value ;

		result = result.replaceAll("(\\d)(th)", "$1") ;
		result = result.replaceAll("(\\d)(st)", "$1") ;		
		result = result.trim() ;

		return result ;
	}

	@Override
	protected Block<ParsedDate> parseRangeValue(
			String str,
			int[] bounds,
			IMeta meta,
			IPropertyProvider propertyProvider,
			Map<String, Object> metaInfo,
			String comment ) {

		return null;
	}

	@Override
	protected void performSpecialProcessing(
			String str,
			ArrayList<Block<ParsedDate>> blockList,
			IMeta meta,
			IPropertyProvider propertyProvider,
			Map<String, Object> metaInfo,
			String comment ) {
		
		if( blockList.isEmpty() )
			return ;
		
		String parserId = null;
		if( metaInfo != null )
			parserId = (String) metaInfo.get( ValuesExtractorV1.MET_INFO_KEY_PARSER_IDENTIFIED ) ;
		
		boolean useExtendedMethod = ( parserId != null && parserId.equals(ParsedDate.ID) ) ;
//		boolean isSingle = blockList.size() == 1 ;			
		
		ArrayList<Block<ParsedDate>> list = new ArrayList<Block<ParsedDate>>() ;
		boolean gotAChange = false ;
		
		for( Block<ParsedDate> blk : blockList ){
			ParsedDate pd = blk.getVal() ;
			if( pd.isRange() ){
				list.add(blk) ;
				continue ;
			}
			
//			boolean isIncompleteRange = false ;
//			String lonelyBound = blk.getMetaInfo( META_KEY_LONELY_BOUND, String.class );
//			if( lonelyBound != null ){
////				isIncompleteRange = true ;
//				if( lonelyBound.equals("lower") ){
//					blk.putMetaInfo( META_KEY_PRECEEDING_COMMENT, "after") ;
//				} else if( lonelyBound.equals("upper")){
//					blk.putMetaInfo( META_KEY_PRECEEDING_COMMENT, "until") ;
//				}
//			}
			
			DateWithAccuracy dwa = (DateWithAccuracy) pd.value() ;
			if( dwa.getAccuracy() != DateWithAccuracy.ACCURACY_YEAR ){
				list.add(blk) ;
				continue ;
			}
			
			String eraStr = blk.getMetaInfo( META_KEY_ERA_SET_DIRECTLY, String.class ) ;
			boolean gotEra = ( eraStr != null && eraDesignators.contains(eraStr.toLowerCase()) ) ;
			
			boolean doNotSkip = false ;

			if( useExtendedMethod )
				doNotSkip = true ;					
			else
				doNotSkip = gotEra ;
			
			if( doNotSkip )
				list.add(blk) ;
			
			gotAChange = true ;
		}
		
		if(gotAChange){
			blockList.clear() ;
			for( Block<ParsedDate> blk : list)
				blockList.add(blk) ;
		}
		
	}

	@Override
	protected boolean areAlternatives(ParsedDate val0, ParsedDate val1) {
		return false;
	}

	@Override
	protected ParsedDate mergeValue(ParsedDate val0, ParsedDate val1) {
		return null;
	}

}
